package com.ming.common.beetl.util;

import cn.hutool.core.util.ReflectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ming.common.Options;
import com.ming.common.SortBy;
import com.ming.common.beetl.vo.IvyPageHeader;
import com.ming.common.beetl.vo.IvyPageResult;
import com.ming.core.beetlsql.BaseEntity;
import org.beetl.sql.clazz.NameConversion;
import org.beetl.sql.core.SQLManager;
import org.beetl.sql.core.page.PageResult;
import org.beetl.sql.core.query.LambdaQuery;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class QueryUtil {

    public static java.util.List<? extends BaseEntity> select(SQLManager sqlManager, BaseEntity baseEntity, Object... params){
        String tableName = baseEntity.getStrValue(StrUtil.snakeToCamel("table_name"));
        String sqlColumn = baseEntity.getStrValue(StrUtil.snakeToCamel("sql_column"));
        LambdaQuery<? extends BaseEntity> query = SqlUtil.dynamicLambdaQuery(sqlManager,tableName);
        where(query, baseEntity, params);
        return query.select(sqlColumn == null ? "*" : sqlColumn);
    }

    public static java.util.List<? extends BaseEntity> selectAll(SQLManager sqlManager,String tableName){
        LambdaQuery<? extends BaseEntity> query = SqlUtil.dynamicLambdaQuery(sqlManager,tableName);
        return query.select();
    }

    public static PageResult<? extends BaseEntity> selectPage(SQLManager sqlManager, String tableName, Options options){
        LambdaQuery<? extends BaseEntity> query = SqlUtil.dynamicLambdaQuery(sqlManager,tableName);
        if(options != null){
            List<SortBy> sortBy = options.getSortBy();
            for (SortBy sort : sortBy) {
                if ("desc".equalsIgnoreCase(sort.getOrder())) {
                    query.desc(StrUtil.camelToSnake(sort.getKey()));
                } else {
                    query.asc(StrUtil.camelToSnake(sort.getKey()));
                }
            }
        }
        PageResult<? extends BaseEntity> page = query.page(options.getPage(), options.getItemsPerPage());
        return page;
    }

    public static IvyPageResult selectIvyPage(SQLManager sqlManager, String tableName, Options options){
        Class<? extends BaseEntity> clazz = SqlUtil.dynamicEntity(sqlManager, tableName);
        LambdaQuery<? extends BaseEntity> query = sqlManager.lambdaQuery(clazz);
        if(options != null){
            List<SortBy> sortBy = options.getSortBy();
            for (SortBy sort : sortBy) {
                if ("desc".equalsIgnoreCase(sort.getOrder())) {
                    query.desc(StrUtil.camelToSnake(sort.getKey()));
                } else {
                    query.asc(StrUtil.camelToSnake(sort.getKey()));
                }
            }
        }
        List<IvyPageHeader> columnList = new ArrayList<>();
        Field[] fields = ReflectUtil.getFields(clazz);
        NameConversion nc = sqlManager.getNc();
        for (Field field : fields){
            columnList.add(new IvyPageHeader(nc.getColName(clazz,field.getName()),field.getName(),true,true));
        }

        PageResult<? extends BaseEntity> page = query.page(options.getPage(), options.getItemsPerPage());
        return new IvyPageResult(page,columnList);
    }

    public static int insertSelective(SQLManager sqlManager, String tableName, Map<String,Object> data){
        Class<? extends BaseEntity> aClass = SqlUtil.dynamicEntity(sqlManager, tableName);
        BaseEntity baseEntity = getEntity(aClass,data);
        LambdaQuery lambdaQuery = getLambdaQuery(sqlManager,aClass);
        return lambdaQuery.insertSelective(baseEntity);
    }

    public static int updateSelectiveById(SQLManager sqlManager, String tableName, Map<String,Object> data,String key){
        Class<? extends BaseEntity> aClass = SqlUtil.dynamicEntity(sqlManager, tableName);
        BaseEntity baseEntity = getEntity(aClass,data);
        LambdaQuery lambdaQuery = getLambdaQuery(sqlManager,aClass);
        lambdaQuery.andEq(key, data.get(key));
        return lambdaQuery.updateSelective(baseEntity);
    }

    public static int deleteById(SQLManager sqlManager, String tableName, Map<String, Object> data,String key) {
        Class<? extends BaseEntity> aClass = SqlUtil.dynamicEntity(sqlManager, tableName);
        LambdaQuery lambdaQuery = getLambdaQuery(sqlManager,aClass);
        lambdaQuery.andEq(key, data.get(key));
        return lambdaQuery.delete();
    }

    private static BaseEntity getEntity(Class<? extends BaseEntity> aClass, Map<String,Object> data){
        BaseEntity convert = null;
        try {
            convert = BeanUtil.convert(data, aClass);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return convert;
    }

    private static LambdaQuery getLambdaQuery(SQLManager sqlManager,Class<? extends BaseEntity> aClass){
        return SqlUtil.dynamicLambdaQuery(sqlManager, aClass);
    }

    private static void where(LambdaQuery<? extends BaseEntity> query, BaseEntity baseEntity, Object[] params) {
        String sqlWhere = baseEntity.getStrValue(StrUtil.snakeToCamel("sql_where"));
        JSONArray array = JSON.parseArray(sqlWhere);
        for (int i=0;i<array.size();i++){
            JSONObject jsonObject = array.getJSONObject(i);
            String column = jsonObject.getString("column");
            String op = jsonObject.getString("op");
            switch (op){
                case "andEq": query.andEq(column,params[i]);break;
            }
        }
    }
}
